package com.lzh.springboot.rabbitmqdemo.producer;

import com.lzh.springboot.rabbitmqdemo.message.Demo01Message;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Component;
import org.springframework.util.concurrent.ListenableFuture;

/**
 * @Description:
 * @Author: LiuZiHao
 * @Date: 2022/5/6 15:04
 */
@Component
public class Demo01Producer {

    /**
     * RabbitTemplate 是 AmqpTemplate 接口的实现类，所以此时使用 AmqpTemplate 亦可。
     * 不过又因为 RabbitTemplate 还实现了其它接口，所以操作会更为丰富。因此，这里我们选择了注入 RabbitTemplate 属性。
     */
    @Autowired
    private RabbitTemplate rabbitTemplate;

    public void syncSend(Integer id) {
        //创建 Demo01Message 消息
        Demo01Message message = new Demo01Message();
        message.setId(id);
        //同步发送消息
        rabbitTemplate.convertAndSend(Demo01Message.EXCHANGE, Demo01Message.ROUTING_KEY, message);
    }

    public void syncSendDefault(Integer id) {
        //创建 Demo01Message 消息
        Demo01Message message = new Demo01Message();
        message.setId(id);
        //同步发送消息
        //默认交换器，隐式地绑定到每个队列，路由键等于队列名称。
        rabbitTemplate.convertAndSend(Demo01Message.QUEUE, message);
    }

    /**
     * 通过 @Async 注解，声明异步调用该方法，从而实现异步消息到 RabbitMQ 中。
     * 因为 RabbitTemplate 并未像 KafkaTemplate 或 RocketMQTemplate 直接提供了异步发送消息的方法，所以我们需要结合 Spring 异步调用来实现。
     * @param id
     * @return
     */
    @Async
    public ListenableFuture<Void> asyncSend(Integer id) {
        try {
            //发送消息
            this.syncSend(id);
            //返回成功的 Future
            return AsyncResult.forValue(null);
        } catch (Throwable e) {
            //返回异常的Future
            return AsyncResult.forExecutionException(e);
        }
    }
}
